package org.ehe.erp.controller.product;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.BaseController;
import org.ehe.common.core.domain.R;
import org.ehe.common.core.exception.BusinessException;
import org.ehe.common.core.validate.AddGroup;
import org.ehe.common.core.validate.EditGroup;
import org.ehe.common.excel.utils.ExcelUtil;
import org.ehe.common.idempotent.annotation.RepeatSubmit;
import org.ehe.common.log.annotation.Log;
import org.ehe.common.log.enums.BusinessType;
import org.ehe.erp.domain.product.ErpProductCategory;
import org.ehe.erp.domain.product.bo.ErpProductCategoryBo;
import org.ehe.erp.domain.product.vo.ErpProductCategoryVo;
import org.ehe.erp.service.product.IErpProductCategoryService;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.ehe.erp.service.product.impl.GenerateCodeServiceImpl;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 产品类别管理
 * @author zhangenen
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/erp/productCategory")
public class ErpProductCategoryController extends BaseController {

    private final IErpProductCategoryService erpProductCategoryService;
    private final GenerateCodeServiceImpl codeService;

    /**
     * 列表
     */
    @SaCheckPermission("erp:category:list")
    @GetMapping("/list")
    public R<List<ErpProductCategoryVo>> list(ErpProductCategoryBo bo) {
        List<ErpProductCategoryVo> list = erpProductCategoryService.queryList(bo);
        return R.ok(list);
    }

    /**
     * 导出
     */
    @SaCheckPermission("erp:category:export")
    @Log(title = "产品分类", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(ErpProductCategoryBo bo, HttpServletResponse response) {
        List<ErpProductCategoryVo> list = erpProductCategoryService.queryList(bo);
        ExcelUtil.exportExcel(list, "产品分类", ErpProductCategoryVo.class, response);
    }

    /**
     * 详情
     * @param id 主键
     */
    @SaCheckPermission("erp:category:query")
    @GetMapping("/{id}")
    public R<ErpProductCategoryVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long id) {
        return R.ok(erpProductCategoryService.queryById(id));
    }

    /**
     * 树形结构
     */
    @SaCheckPermission("erp:category:query")
    @GetMapping("/categoryTree")
    public R<List<Tree<Long>>> categoryTree(ErpProductCategoryBo category) {
        return R.ok(erpProductCategoryService.selectCategoryTreeList(category));

    }

    /**
     * 数据联动
     */
    @SaCheckPermission("erp:category:query")
    @GetMapping("/category/{parentId}")
    public R<List<ErpProductCategory>> categoryList(@PathVariable Long parentId) {
        return R.ok(erpProductCategoryService.categoryList(parentId));

    }
    /**
     * 新增方法
     */
    @SaCheckPermission("erp:category:add")
    @Log(title = "产品分类新增", linkType = "product", businessType = BusinessType.INSERT,  nameField = "name")
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody ErpProductCategoryBo bo) {
        try {
            // 验证唯一性
            if (!erpProductCategoryService.isUniqueNameAndCode(bo)) {
                String parentName = "";
                if (bo.getParentId() != null && bo.getParentId() > 0) {
                    parentName = erpProductCategoryService.getCategoryNameById(bo.getParentId());
                }
                return R.fail(String.format("创建失败！在分类[%s]下已存在名称为[%s]的分类",
                    StrUtil.isBlank(parentName) ? "根目录" : parentName, bo.getName()));
            }

            // 执行新增
            boolean success = erpProductCategoryService.insertByBo(bo);
            if (success) {
                return R.ok("成功创建分类：" + bo.getName());
            } else {
                return R.fail("创建分类失败，请重试");
            }

        } catch (BusinessException e) {
            return R.fail(e.getMessage());
        } catch (Exception e) {
            log.error("创建分类失败", e);
            return R.fail("创建分类失败：" + e.getMessage());
        }
    }

    /**
     * 修改方法
     */
    @SaCheckPermission("erp:category:edit")
    @Log(title = "产品分类编辑", linkType = "product", businessType = BusinessType.UPDATE,  nameField = "name")
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ErpProductCategoryBo bo) {

        if (bo.getId() == null) {
            return R.fail("分类ID不能为空");
        }

        // 1. 校验产品分类名称不能重复
        if (!erpProductCategoryService.isUniqueNameForUpdate(bo)) {
            return R.fail("修改产品分类失败，分类名称'" + bo.getName() + "'已存在");
        }

        // 2. 校验产品分类编码不能重复
        if (!erpProductCategoryService.isUniqueCodeForUpdate(bo)) {
            return R.fail("修改产品分类失败，分类编码'" + bo.getCode() + "'已存在");
        }

        // 获取当前分类信息（用于后续校验和提示）
        ErpProductCategoryVo currentCategory = erpProductCategoryService.queryById(bo.getId());
        if (currentCategory == null) {
            return R.fail("要修改的分类不存在");
        }

        // 3. 校验产品分类不能修改为自己
        if (bo.getId().equals(bo.getParentId())) {
            return R.fail("修改产品分类失败，不能将'" + currentCategory.getName() + "'设置为自己的父分类");
        }

        // 4. 校验产品分类不能修改为自己的子分类
        if (bo.getParentId() != null && bo.getParentId() > 0) {
            if (!erpProductCategoryService.isValidParentChange(bo.getId(), bo.getParentId())) {
                String parentName = erpProductCategoryService.getCategoryNameById(bo.getParentId());
                return R.fail("修改产品分类失败，不能将'" + currentCategory.getName() + "'设置为其子分类'" + parentName + "'的父分类");
            }
        }

        return toAjax(erpProductCategoryService.updateByBo(bo));
    }

    /**
     * 删除方法
     */
    @SaCheckPermission("erp:category:remove")
    @Log(title = "产品分类删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
        try {
            return toAjax(erpProductCategoryService.deleteWithValidByIds(List.of(ids), true));
        } catch (BusinessException e) {
            return R.warn(e.getMessage());
        } catch (Exception e) {
            log.error("删除分类失败", e);
            return R.fail("删除失败：" + e.getMessage());
        }
    }

    /**
     * 生成编码接口
     */
    @GetMapping("/generateCode")
    public R<Map<String, Object>> generateCode(@RequestParam(required = false) Long parentId) {
        try {
            GenerateCodeServiceImpl.CodeGenerateResult result =
                codeService.generateCategoryCode(parentId, "预览分类");

            if (result.isSuccess()) {
                Map<String, Object> data = new HashMap<>();
                data.put("code", result.getCode());
                data.put("fullCode", result.getFullCode());
                data.put("fullName",result.getFullName());
                data.put("level", result.getLevel());
                data.put("sequenceNo", result.getSequenceNo());
                data.put("preview", String.format("层级：%d，完整编码：%s", result.getLevel(), result.getFullCode()));

                return R.ok(result.getMessage(), data);
            } else {
                return R.fail(result.getMessage());
            }
        } catch (Exception e) {
            log.error("生成编码失败", e);
            return R.fail("生成编码失败：" + e.getMessage());
        }
    }

    /**
     * 上移分类
     */
    @PostMapping("/moveUp/{id}")
    public R<Void> moveUp(@NotNull(message = "主键不能为空") @PathVariable Long id) {
        try {
            return toAjax(erpProductCategoryService.moveUp(id));
        } catch (BusinessException e) {
            return R.warn(e.getMessage());
        }
    }

    /**
     * 下移分类
     */
    @PostMapping("/moveDown/{id}")
    public R<Void> moveDown(@NotNull(message = "主键不能为空") @PathVariable Long id) {
        try {
            return toAjax(erpProductCategoryService.moveDown(id));
        } catch (BusinessException e) {
            return R.warn(e.getMessage());
        }
    }

    /**
     * 查找父类
     */
    @PostMapping("/getCategoryPath/{childId}")
    public R<List<Long>> getCategoryPath(@NotNull(message = "主键不能为空") @PathVariable Long childId) {

        try {
            List<ErpProductCategory> categoryPath = erpProductCategoryService.getCategoryPath(childId);
            List<Long> collect = categoryPath.stream().map(ErpProductCategory::getId).collect(Collectors.toList());
            return R.ok(collect);
        } catch (BusinessException e) {
            return R.warn(e.getMessage());
        }
    }


}
